import { PerformanceFilds } from './interface'
// import { overrideConsole } from './utils'
class Monitor {
  static instance
  private performance: PerformanceFilds
  constructor () {
    this.performance = {
      FPT: null, // 首次渲染时间（白屏时间） 小程序 onShow (first page) - onLaunch (app)
      TTI: null, // 首次可交互时间
      Ready: null, // HTML加载完成时间， 即DOM Ready时间
      Load: null, // 页面完全加载时间
      FirstByte: null, // 首包时间
      DNS: null, // DNS查询耗时
      TCP: null, // TCP连接耗时
      TTFB: null, // 请求响应耗时
      Trans: null, // 内容传输耗时
      DOM: null, // DOM解析耗时
      Res: null, // 资源加载耗时
    }
    if (!Monitor.instance) {
      Monitor.instance = true
      this.init()
    }
  }

  init () {
    this.watchWindow()
  }

  watchWindow () {
    // 重写window.onerror
    // 无法捕获资源异常的错误，因为网络请求异常不会事件冒泡
    // window.onerror = function (
    //   event: Event | string,
    //   source?: string,
    //   lineno?: number,
    //   colno?: number,
    //   error?: Error,
    // ) {
    //   console.log('I make a mistake', event, source, lineno, colno, error)
    //   return true
    //   // return true // 返回 true 的时候，异常不会向上抛出，控制台不会输出错误
    // }
    // 捕获网络请求错误 捕获阶段获取
    window.addEventListener('error', (e: any) => {
      // e.preventDefault()
      if (e.target !== window) { // 避免重复上报 onerror
        console.error('引用资源地址错误', {
          url: window.location.href, // 引用资源地址
          srcUrl: e.target.src, // 资源加载出错地址
          target: e.target.tagName,
        })
      }
    }, true)

    // 捕捉promise
    window.addEventListener('unhandledrejection', function (e: PromiseRejectionEvent) {
      console.error('unhandledrejection', e.reason)
      e.preventDefault()
      return true
    })

    window.onload = this.calcPerformance
    // overrideConsole()
  }

  calcPerformance () {
    const {
      responseStart,
      loadEventStart,
      domContentLoadedEventEnd,
      domInteractive,
      fetchStart,
      domainLookupEnd,
      domainLookupStart,
      connectEnd,
      connectStart,
      requestStart,
      responseEnd,
      // secureConnectionStart,
    } = window.performance.timing
    this.performance.FPT = responseEnd - fetchStart
    this.performance.TTI = domInteractive - fetchStart
    this.performance.Ready = domContentLoadedEventEnd - fetchStart
    this.performance.Load = loadEventStart - fetchStart
    this.performance.FirstByte = responseStart - domainLookupStart
    this.performance.DNS = domainLookupEnd - domainLookupStart
    this.performance.TCP = connectEnd - connectStart
    this.performance.TTFB = responseStart - requestStart
    this.performance.Trans = responseEnd - responseStart
    this.performance.DOM = domInteractive - responseEnd
    this.performance.Res = loadEventStart - domContentLoadedEventEnd
  }
}
(window as any).ErrorWatch = new Monitor()
